#include <gdk/gdk.h>
#include <gdk/gdkx.h>
#include <stdio.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>
#include <X11/Xatom.h>
#include <X11/keysym.h>

static GdkFilterReturn
gdk_events_filter (GdkXEvent *xevent, GdkEvent *event, gpointer data)
{
        XEvent *xev = (XEvent *) xevent;
        guint keycode;
        keycode = xev->xkey.keycode;
        printf("xev-type: %d, keycode: %d\n", xev->type, keycode);
        if (xev->type != KeyPress) {
            return GDK_FILTER_CONTINUE;
        }

        return GDK_FILTER_REMOVE;
}

gboolean mygdk_grab_key(GdkDisplay *gdpy, GdkWindow *win, KeyCode keycode) {
        guint modmask = AnyModifier;
        gint ret;
        
        Display *dpy = GDK_DISPLAY_XDISPLAY (gdpy);
        /* get the current X Display */
        /* don't abort on error */
        //gdk_error_trap_push ();
        gdk_x11_display_error_trap_push(gdpy);
        /* grab the key if possible */
        ret = XGrabKey (dpy, keycode, modmask,
                        GDK_WINDOW_XID (win), True,
                        GrabModeAsync, GrabModeAsync);
        if (ret == BadAccess) {
               fprintf(stderr, "Failed to grab modmask=%u, keycode=%li\n",
                             LockMask | modmask, (long int) keycode);
                return FALSE;
        }

        /* grab the lock key if possible */
        ret = XGrabKey (dpy, keycode, LockMask | modmask,
                        GDK_WINDOW_XID (win), True,
                        GrabModeAsync, GrabModeAsync);
        if (ret == BadAccess) {
               fprintf(stderr, "Failed to grab modmask=%u, keycode=%li\n",
                             LockMask | modmask, (long int) keycode);
                return FALSE;
        }
        //gdk_flush ();
        gdk_display_flush(gdpy);
        //gdk_error_trap_pop ();
        gdk_x11_display_error_trap_pop(gdpy);

        return TRUE;
}

int main(int argc, char *argv[]) {
    GdkScreen *screen = NULL;
    GdkWindow *window = NULL;
    KeyCode keycode;
    if(!gdk_init_check (&argc, &argv) ) {
        return -1;
    }
    GdkDisplay *gdpy = gdk_display_get_default();
    Display *dpy = GDK_DISPLAY_XDISPLAY (gdpy);
    if (!gdk_init_check (&argc, &argv)) {
        return FALSE;
    }
    screen = gdk_screen_get_default();
    printf("screen: %p\n", screen);
    window = gdk_screen_get_root_window(screen);
    keycode = XKeysymToKeycode(dpy, XK_Num_Lock);
    mygdk_grab_key(gdpy, window, keycode);
    keycode = XKeysymToKeycode(dpy, XK_Caps_Lock);
    mygdk_grab_key(gdpy, window, keycode);
    gdk_window_add_filter(window, gdk_events_filter, NULL);
    GMainLoop *mainloop = g_main_loop_new(NULL, TRUE);
    g_main_loop_run(mainloop);
    return 0;
    
}
